﻿using CQRSFramework.Common.Components;
using CQRSFramework.Infrustructures;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace CQRSFramework.Commands.Impl
{
    public class CommandHandlerProvider : ICommandHandlerProvider
    {
        private readonly IDictionary<Type, IList<Type>> _dictionary = new Dictionary<Type, IList<Type>>();
        public CommandHandlerProvider(Assembly[] assemblies)
        {
            foreach (var assembly in assemblies)
            {
                foreach (var handlerType in assembly.GetTypes()
                            .Where(t => t.GetInterfaces()
                                .Any(a => a.IsGenericType
                                    && (a.GetGenericTypeDefinition() == typeof(ICommandHandler<>)))))
                {
                    var handlerInterfaces = handlerType.GetInterfaces().Where(a => a.IsGenericType);
                    foreach (var handlerInterface in handlerInterfaces)
                    {
                        IList<Type> types;
                        var handleType = handlerInterface.GetGenericArguments().Single();
                        if (!_dictionary.TryGetValue(handleType, out types))
                        {
                            types = new List<Type>();
                            _dictionary.Add(handleType, types);
                        }
                        types.Add(handlerInterface);
                    }
                }
            }
        }
        public IEnumerable<ICommandHandler<T>> GetCommandHandlers<T>(T command) where T : class, ICommand
        {
            IList<Type> handlers;
            if (_dictionary.TryGetValue(command.GetType(), out handlers))
            {
                return handlers.Select(e => (ObjectContainer.Resolve(e) as ICommandHandler<T>));
            };
            return null;
        }
    }
}
